package rgbos.forum.search;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.Vector;

import org.compass.core.Compass;
import org.compass.core.CompassHit;
import org.compass.core.CompassHits;
import org.compass.core.CompassSession;
import org.compass.core.CompassTemplate;
import org.compass.core.config.CompassConfiguration;
import org.compass.core.config.CompassConfigurationFactory;
import org.compass.core.config.CompassEnvironment;

import rgbos.forum.domain.Auditor;
import rgbos.forum.domain.Post;

public class CompassSearchEngine implements AbstractSearchEngine {	

	Compass compass_;
	public CompassSearchEngine() {
		CompassConfiguration conf = CompassConfigurationFactory
         							.newConfiguration()
         							.setConnection("genData");
        conf.addClass(Post.class);

        compass_ = conf.buildCompass();
	}

	@Override
	public synchronized Vector<PostRate> searchByAuthor(String name) {
		CompassSession tSession = compass_.openSession();
		CompassHits hits = tSession.find("author:" + name +"");
		Vector<PostRate> ans = arrangeSearchResults(hits);
		tSession.close();
        return ans;
	}

	@Override
	public synchronized Vector<PostRate> searchByContent(String searchQuery) {
		CompassSession tSession = compass_.openSession();
		CompassHits hits = tSession.find("body:" + searchQuery +"");
		Vector<PostRate> ans = arrangeSearchResults(hits);
		tSession.close();
        return ans;
	}

	@Override
	public synchronized Vector<PostRate> searchByDate(String date) {
		CompassSession tSession = compass_.openSession();
		CompassHits hits = tSession.find("date:" + date +"");
		Vector<PostRate> ans = arrangeSearchResults(hits);
		tSession.close();
        return ans;
	}

	private Vector<PostRate> arrangeSearchResults(CompassHits hits) {
		Iterator<CompassHit> hitsIterator = hits.detach().iterator();		
		Vector<PostRate> ratedPosts = new Vector<PostRate>();
		while(hitsIterator.hasNext()) {
			CompassHit hit = hitsIterator.next();
			PostRate post = new PostRate((Post)(hit.data()),hit.getScore());
			ratedPosts.add(post);
		}
		Collections.sort(ratedPosts);		
		return ratedPosts;
	}

	@Override
	public synchronized void indexPost(Post message) {
		CompassSession tSession = compass_.openSession();
		tSession.save(message);
		tSession.close();
		Auditor.Log("The post " + message.getTitle_() + " was added to the search index", this.getClass());
	}

	@Override
	public void deletePost(Post message) {
		CompassSession tSession = compass_.openSession();
		tSession.delete(message);
		tSession.close();
		Auditor.Log("The post " + message.getTitle_() + " was deleted from the search index", this.getClass());
	}

	@Override
	public void modifyPost(Post oldMessage, Post newMessage) {
		CompassSession tSession = compass_.openSession();		
		tSession.delete(oldMessage);
		tSession.save(newMessage);
		tSession.close();
		Auditor.Log("The post " + oldMessage.getTitle_() + " was modified in the search index", this.getClass());
	}

	@Override
	public Vector<PostRate> searchByDate(String from, String to) {
		Vector<PostRate> ans = new Vector<PostRate>();

		try {
			SimpleDateFormat tDateFormat = new SimpleDateFormat("dd/mm/yyyy");
			Calendar start = Calendar.getInstance();
			Calendar end = Calendar.getInstance();			
			Date fromDate = tDateFormat.parse(from);
			Date toDate = tDateFormat.parse(to);
			start.setTime(fromDate);
			end.setTime(toDate);
			String dateFormatted = tDateFormat.format(start.getTime());
			while(start.compareTo(end) <= 0) {
				Vector<PostRate> searchAns = searchByDate(tDateFormat.format(start.getTime()));
				if (searchAns != null && !searchAns.isEmpty())
					ans.addAll(searchAns);
				start.add(Calendar.DAY_OF_MONTH, 1);
				Date date = start.getTime();
				dateFormatted = tDateFormat.format(date);
			}
		} catch (ParseException e) {
			// The date should be formated correctly because the clients doesn't format it himself.
		}
		return ans;
	}
}